package com.cennavi.minenavidemo.presenter;

import android.content.Context;
import android.graphics.Point;

import com.minedata.minenavi.mapdal.LatLng;
import com.minedata.minenavi.mapdal.PoiItem;
import com.minedata.minenavi.mapdal.Tools;
import com.minedata.minenavi.navi.RouteBase;
import com.minedata.minenavi.poiquery.DistrictItem;
import com.minedata.minenavi.poiquery.DistrictSearch;
import com.minedata.minenavi.poiquery.DistrictSearchQuery;
import com.minedata.minenavi.poiquery.GeocodeResult;
import com.minedata.minenavi.poiquery.GeocodeSearch;
import com.minedata.minenavi.poiquery.Inputtips;
import com.minedata.minenavi.poiquery.InputtipsQuery;
import com.minedata.minenavi.poiquery.LatLonPoint;
import com.minedata.minenavi.poiquery.MineNaviException;
import com.minedata.minenavi.poiquery.PoiResult;
import com.minedata.minenavi.poiquery.PoiSearch;
import com.minedata.minenavi.poiquery.RegeocodeAddress;
import com.minedata.minenavi.poiquery.RegeocodeQuery;
import com.minedata.minenavi.poiquery.RegeocodeResult;
import com.minedata.minenavi.poiquery.RoutePOIItem;
import com.minedata.minenavi.poiquery.RoutePOISearch;
import com.minedata.minenavi.poiquery.RoutePOISearchQuery;
import com.minedata.minenavi.poiquery.SearchErrorCode;
import com.minedata.minenavi.poiquery.SortType;
import com.minedata.minenavi.poiquery.Tip;

import java.util.ArrayList;
import java.util.List;

public class PoiPresenter {
    private static final String TAG = "PoiPresenter";
    private Context mContext;
    private MapPresenter mMapPresenter;
    private NaviPresenter mNaviPresenter;
    private RoutePOISearch search;
    private GeocodeSearch geocoderSearch;
    private DistrictSearch districtSearch;
    private Inputtips inputTips;
    private PoiSearch poiSearch = null;
    private PoiSearch.Query query = null;

    public interface OnPoiSearchListener {
        //搜索完成
        void onSearchComplete(ArrayList<PoiItem> poiItems, boolean isSuccess);

        void onIdSearch(PoiItem poiItem, boolean isSuccess);

        void onRegeocodeSearched(RegeocodeAddress regeocodeAddress);

        void onDistrictSearch(DistrictItem districtItem);

        void onGetInputtips(List<Tip> tips);
    }

    private OnPoiSearchListener mOnPoiSearchListener;

    private PoiPresenter() {
    }

    private static class SingletonHolder {
        public static final PoiPresenter instance = new PoiPresenter();
    }

    public static PoiPresenter getInstance() {
        return SingletonHolder.instance;
    }

    public void setOnPoiSearchListener(OnPoiSearchListener onPoiSearchListener) {
        this.mOnPoiSearchListener = onPoiSearchListener;
    }

    public void init(Context context) {
        this.mContext = context;
        mMapPresenter = MapPresenter.getInstance();
        mNaviPresenter = NaviPresenter.getInstance();
    }

    public void initRoutePOISearch() {
        search = new RoutePOISearch(mContext);
        search.setPoiSearchListener((result, errorCode) -> {
            if (errorCode == SearchErrorCode.none) {
                ArrayList<RoutePOIItem> routePOIItems = result.getRoutePois();
                ArrayList<PoiItem> poiItems = new ArrayList<>();

                for (RoutePOIItem routePOIItem : routePOIItems) {
                    PoiItem poiItem = new PoiItem();
                    poiItem.title = routePOIItem.getTitle();
                    poiItem.location = routePOIItem.getPoint();
                    poiItems.add(poiItem);
                }

                mMapPresenter.showPoiSearchResultLayer(poiItems);
            } else {
                mOnPoiSearchListener.onSearchComplete(null, false);
            }
        });
    }

    public void initRegeocode() {
        geocoderSearch = new GeocodeSearch(mContext);
        geocoderSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() {
            @Override
            public void onGeocodeSearched(GeocodeResult geocodeResult, int resultID) {

            }

            @Override
            public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int resultID) {
                if (resultID == SearchErrorCode.none) {
                    List<RegeocodeAddress> regeocodeAddresses = regeocodeResult.getRegeocodeAddressList();

                    if (regeocodeAddresses != null && regeocodeAddresses.size() > 0) {
                        mOnPoiSearchListener.onRegeocodeSearched(regeocodeAddresses.get(0));
                    }
                }
            }
        });
    }

    public void initDistrictSearch() {
        districtSearch = new DistrictSearch(mContext);

        districtSearch.setOnDistrictSearchListener(districtResult -> {
            if (districtResult != null && districtResult.getMineNaviException().getErrorCode() == MineNaviException.CODE_MINENAVI_SUCCESS) {
                List<DistrictItem> districtItems = districtResult.getDistrict();

                if (districtItems != null && districtItems.size() > 0) {
                    DistrictItem districtItem = districtItems.get(0);
                    Point point = Tools.latLonPointToPoint(districtItem.getCenter());
                    mMapPresenter.getMineMap().setPointToCenter(point.x, point.y);
                    mMapPresenter.getMineMap().removeAllOverlays();

                    LatLng latLng = Tools.pointToLatLng(point);
                    mMapPresenter.addPoiMarker(latLng);

                    String[] districtBoundarys = districtItem.districtBoundary();
                    List<LatLng> locations = new ArrayList<>();

                    if (districtBoundarys != null) {
                        for (String districtBoundary : districtBoundarys) {
                            String[] splitLocations = districtBoundary.split(";");

                            for (String splitLocation : splitLocations) {
                                String[] splitLonLat = splitLocation.split(",");
                                LatLng location = new LatLng(Double.parseDouble(splitLonLat[1]), Double.parseDouble(splitLonLat[0]));
                                locations.add(location);
                            }
                        }

                        mMapPresenter.addPoiPolyline(locations);
                    }

                    mOnPoiSearchListener.onDistrictSearch(districtItem);
                }
            }
        });
    }

    public void initPoiSearch() {
        poiSearch = new PoiSearch(mContext);

        poiSearch.setOnPoiSearchListener(new PoiSearch.OnPoiSearchListener() {
            @Override
            public void onPoiItemSearched(PoiItem poiItem, int errorCode) {
                if (errorCode == SearchErrorCode.none) {
                    mOnPoiSearchListener.onIdSearch(poiItem, true);
                }
            }

            @Override
            public void onPoiSearched(PoiResult poiResult, int errorCode) {
                if (errorCode == SearchErrorCode.none) {
                    if (poiResult != null && poiResult.getPois() != null && poiResult.getPois().size() > 0) {
                        mOnPoiSearchListener.onSearchComplete(poiResult.getPois(), true);
                    } else {
                        mOnPoiSearchListener.onSearchComplete(new ArrayList<>(), true);
                    }
                } else {
                    mOnPoiSearchListener.onSearchComplete(null, false);
                }
            }
        });
    }

    public void initInputtips() {
        inputTips = new Inputtips(mContext);

        inputTips.setInputtipsListener(new Inputtips.InputtipsListener() {
            @Override
            public void onGetInputtips(List<Tip> inputTips, int resultID) {

                if (resultID == SearchErrorCode.none) {
                    mOnPoiSearchListener.onGetInputtips(inputTips);
                }
            }
        });
    }

    /**
     * 逆地理编码查询
     */
    public void reGeocode(LatLonPoint latLonPoint) {
        RegeocodeQuery query = new RegeocodeQuery(latLonPoint);
        query.setSortType(SortType.SORT_TYPE_DISTANCE);
        query.setExtensions("all");
        geocoderSearch.getFromLocationAsyn(query);
    }

    public void startRoutePOISearch(LatLonPoint point, RouteBase routeBase, String keyword, String type, int range) {
        RoutePOISearchQuery query =
                new RoutePOISearchQuery(point, routeBase, keyword, type, range);
        search.setQuery(query);
        search.searchRoutePOIAsyn();
    }

    public void startDistrictSearch(String district) {
        DistrictSearchQuery query = new DistrictSearchQuery();
        query.setKeywords(district);
        query.setShowBoundary(true);
        query.setSubDistrict(1);
        districtSearch.setQuery(query);
        districtSearch.searchDistrictAsyn();
    }

    public void startKeywordSearch(String key) {
        query = new PoiSearch.Query(key, "", "210100");
        query.setCityLimit(true);
        query.setLocation(new LatLonPoint(41.80196, 123.43326));
        query.requireSubPois(true);
        query.setExtensions("all");
        query.setPageSize(20);
        poiSearch.setQuery(query);
        poiSearch.searchPOIAsyn();
    }

    public void startInputtips(String key) {
        InputtipsQuery inputquery = new InputtipsQuery(key, "");
        inputquery.setLocation(new LatLonPoint(39.915446, 116.403869));
        inputTips.setQuery(inputquery);
        inputTips.requestInputtipsAsyn();
    }

    public void startIdSearch(String id) {
        poiSearch.searchPOIIdAsyn(id);
    }

    public void startPolygonSearch(List<LatLonPoint> points) {
        PoiSearch.SearchBound bound = new PoiSearch.SearchBound(points);
        poiSearch.setBound(bound);//设置多边形区域
        query = new PoiSearch.Query("", "快餐店|中餐馆|冷饮");
        query.requireSubPois(true);
        query.setPageSize(10);
        poiSearch.setQuery(query);
        poiSearch.searchPOIAsyn();
    }

    public void startTypeSearch(String type) {
        PoiSearch.SearchBound bound = new PoiSearch.SearchBound(new LatLonPoint(39.915446, 116.403869), 2000);
        poiSearch.setBound(bound);//设置周边搜索的中心点以及半径
//        query = new PoiSearch.Query("肯德基|麦当劳", "快餐店|中餐馆|冷饮", "110000");
        // 离线
        query = new PoiSearch.Query("", type, "110000");
        query.requireSubPois(true);
        query.setPageSize(5);
        poiSearch.setQuery(query);
        poiSearch.searchPOIAsyn();
    }

    public void loadPrevious() {
        if (poiSearch != null)
            poiSearch.loadPreviousPage();
    }

    public void loadNext() {
        if (poiSearch != null)
            poiSearch.loadNextPage();
    }
}